package com.yunhe.inspect.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import com.yunhe.common.constant.InSpectConsts;
import com.yunhe.inspect.model.ExportHistoryRectificationSheetVO;
import com.yunhe.inspect.model.ExportHistoryVO;
import com.yunhe.inspect.model.InspectOrderItem;
import com.yunhe.inspect.service.ExportHistoryService;
import com.yunhe.inspect.service.HelpService;
import com.yunhe.inspect.service.HistoryService;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Sheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
public class ExportHistoryServiceImpl implements ExportHistoryService {
    private static Logger log = LoggerFactory.getLogger(ExportHistoryServiceImpl.class);

    @Autowired
    private Environment environment;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private HelpService helpService;

    @Override
    public String  export(String ids) {
        if(StrUtil.isBlank(ids)){
            return null;
        }

        //查询集合
        List<ExportHistoryVO> list = new ArrayList<>();
        String[] arr = ids.split(",");
        for(String id : arr){
            ExportHistoryVO vo = historyService.detail(Long.valueOf(id));
            list.add(vo);
        }

        //生成excel
        return this.export(list, getFilePath());
    }

    @Override
    public String  export(List<ExportHistoryVO> list) {
        return this.export(list, getFilePath());
    }

    @Override
    public String  export(List<ExportHistoryVO> list, String filePath) {
        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getBigWriter(filePath);

        //循环生成sheet
        for(int k = 0; k<list.size(); k++){
            if(k>0){ //超过一个 创建新的sheet
                writer.setSheet(list.get(k).getNumber());
            }
            initSheet(writer, list.get(k), k); //sheet初始化设置
            generateSheet(writer, list.get(k)); //生成sheet
        }

        writer.close(); // 关闭writer，释放内存
        return filePath;
    }

    //生成sheet
    private void generateSheet(ExcelWriter writer, ExportHistoryVO vo) {
        int curRow = 0; //记录当前工作的行号 每写完一行 当前行号+1

        //输出工单名称
        writer.merge(5, vo.getTitle());
        curRow++;

        //输出巡检单编号
        writer.merge(5, "巡检单编号："+vo.getNumber());
        curRow++;

        //输出企业名称
        writer.writeCellValue(0, curRow,"企业名称：");
        writer.writeCellValue(1, curRow,vo.getCompanyName());
        //输出房源名称
        writer.writeCellValue(2, curRow,"房源名称：");
        writer.writeCellValue(3, curRow,vo.getOfficeName());
        //输出工单创建日期
        writer.writeCellValue(4, curRow,"日期：");
        writer.writeCellValue(5, curRow, vo.getCreateTime());
        curRow++;

        //输出检查人
        writer.writeCellValue(0, curRow,"检查人：");
        writer.writeCellValue(1, curRow, helpService.getUserName(vo.getCheckPerson(), "/"));
        //输出受检人
        writer.writeCellValue(2, curRow,"受检人：");
        //writer.writeCellValue(3, curRow, helpService.getUserName(vo.getTestedPerson(), "/"));
        writePic(writer, vo.getInspectedPersonSignature(), 3, curRow); //受检人签名图片
        writer.passRows(curRow-1); //跳过前面的行数 换行输出
        writer.setRowHeight(curRow, 50);
        curRow++;

        //输出检查项目栏
        writer.merge(5, "检查项目：");
        curRow++;
        //输出检查项目列表
        for(int i=0; i<vo.getInspectOrderItems().size(); i++){
            writer.writeCellValue(0, curRow, i+1);
            writer.merge(curRow, curRow, 1, 3,  vo.getInspectOrderItems().get(i).getItemContent(), true);
            writer.merge(curRow, curRow, 4, 5,  handleItemValue(vo.getInspectOrderItems().get(i)), true);
            curRow++;
        }
        //上述循环结束后 就已经换行

        //输出整改单
        handleRectificationSheet(writer, curRow, vo.getRectificationSheetList());
    }

    //检查结果数据转换
    private String handleItemValue(InspectOrderItem inspectOrderItem) {
        if(inspectOrderItem.getItemType().equals(InSpectConsts.Item_Type.FillBlanks.value())){ //填空
            return inspectOrderItem.getItemValue();
        }
        if(inspectOrderItem.getItemType().equals(InSpectConsts.Item_Type.SingleChoice.value())){ //单选
            if(inspectOrderItem.getItemValue().equals("01")){
                return "是";
            } else {
                return "否";
            }
        }
        return "/";
    }

    //输出整改单整改单
    private void handleRectificationSheet(ExcelWriter writer, int curRow, List<ExportHistoryRectificationSheetVO> rectificationSheetList) {
        if(CollectionUtil.isEmpty(rectificationSheetList)){ //是否有整改单
            return;
        }

        for(int i=0; i<rectificationSheetList.size(); i++){
            ExportHistoryRectificationSheetVO vo = rectificationSheetList.get(i);

            //如果有多个整改单 那么每个整改单后面加上序号
            String suffix = "";
            if(rectificationSheetList.size()>1){
                suffix = StrUtil.format("({})", i+1);
                //curRow++;//空出一行
            }

            //输出检查的问题
            writer.merge(curRow, curRow, 0, 1,  StrUtil.format("检查问题{}：", suffix), true);
            writer.merge(curRow, curRow, 2, 5,  vo.getCheckResult(), true);
            writer.setRowHeight(curRow, 50);
            curRow++;

            //输出要求整改时间
            writer.merge(curRow, curRow, 0, 1,  "责令你单位于", true);
            writer.writeCellValue(2, curRow, vo.getLimitTime());
            writer.merge(curRow, curRow, 3, 5,  "前整改完成，逾期不整改将建议区安监执法部门给予行政处罚，由此造成事故的，依法追求有关人员的责任。", true);
            writer.setRowHeight(curRow, 50);
            curRow++;

            //输出图片信息与整改内容
            writer.merge(curRow, curRow+1, 0, 0,  StrUtil.format("整改上传{}：", suffix), true);
            writer.writeCellValue(1, curRow,"内容");
            writer.merge(curRow, curRow, 2, 5,  vo.getRectificationContent(), true);
            writer.writeCellValue(1, curRow+1,"图片");
            writePic(writer, vo.getImgUrlList(), curRow+1); //写入图片
            writer.setRowHeight(curRow, 40);
            writer.setRowHeight(curRow+1, 50);
            curRow += 2;

            //输出复审结果
            writer.merge(curRow, curRow, 0, 1,  StrUtil.format("复审意见{}：", suffix), true);
            writer.merge(curRow, curRow, 2, 5,  vo.getReviewResult(), true);
            writer.setRowHeight(curRow, 50);
            curRow++;

            //输出复审时间
            writer.merge(curRow, curRow, 0, 1,  StrUtil.format("复审时间{}：", suffix), true);
            writer.merge(curRow, curRow, 2, 5,  vo.getReviewTime(), true);
            curRow++;
        }
    }

    //单元格写入图片
    private void writePic(ExcelWriter writer, List<String> imgList, int curRow) {
        if(Objects.isNull(imgList)){
            return;
        }
        for(int i=0; i<imgList.size(); i++){
            writePic(writer, imgList.get(i), 2+i, curRow);
            /*try{
                URL url = new URL(imgList.get(i));
                URLConnection urlcon = url.openConnection();
                byte[] pictureData = readInputStream(urlcon.getInputStream());
                if(Objects.nonNull(pictureData)) {
                    writePic(writer, 2+i, curRow, pictureData, HSSFWorkbook.PICTURE_TYPE_JPEG);
                }
            } catch (Exception e){
                log.error("图片写入异常：{}",imgList.get(i));
            }*/
        }
    }
    private void writePic(ExcelWriter writer, String imgUrl, int column, int curRow) {
        if(StrUtil.isBlank(imgUrl)){
            return;
        }
        try{
            URL url = new URL(imgUrl);
            URLConnection urlcon = url.openConnection();
            byte[] pictureData = readInputStream(urlcon.getInputStream());
            if(Objects.nonNull(pictureData)) {
                writePic(writer, column, curRow, pictureData, HSSFWorkbook.PICTURE_TYPE_JPEG);
            }
        } catch (Exception e){
            log.error("图片写入异常：{}",imgUrl);
        }
    }

    //sheet初始化设置
    private void initSheet(ExcelWriter writer, ExportHistoryVO vo, int index) {
        //修改sheet名称
        String sheetName = StrUtil.format("{}-{}", index+1, vo.getTitle());
        writer.renameSheet(sheetName);

        //样式设置
        StyleSet style = writer.getStyleSet();
        //style.setWrapText();
        CellStyle cellStyle = style.getHeadCellStyle();
        cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); //白色背景
        cellStyle.setWrapText(true); //自动换行

        //单元格宽度
        int columnWidth = 252*15+323;
        writer.getSheet().setColumnWidth(0, columnWidth);
        writer.getSheet().setColumnWidth(1, columnWidth);
        writer.getSheet().setColumnWidth(2, columnWidth);
        writer.getSheet().setColumnWidth(3, columnWidth);
        writer.getSheet().setColumnWidth(4, columnWidth);
        writer.getSheet().setColumnWidth(5, columnWidth);
    }

    //插入图片
    private void writePic(ExcelWriter writer, int x, int y, byte[] pictureData, int picType) {
        Sheet sheet = writer.getSheet();
        Drawing drawingPatriarch = sheet.createDrawingPatriarch();
        //设置图片单元格位置
        ClientAnchor anchor = drawingPatriarch.createAnchor(0, 0, 0, 0, x, y, x + 1, y + 1);
        //随单元格改变位置和大小
        anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
        //添加图片
        int pictureIndex = sheet.getWorkbook().addPicture(pictureData, picType);
        drawingPatriarch.createPicture(anchor, pictureIndex);
    }

    /**
     * 从输入流中获取数据
     * @param inStream 输入流
     * @return
     * @throws Exception
     */
    public static byte[] readInputStream(InputStream inStream) {
        try {
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while( (len=inStream.read(buffer)) != -1 ){
                outStream.write(buffer, 0, len);
            }
            inStream.close();
            return outStream.toByteArray();
        } catch (Exception ex){
            log.error("从输入流中获取数据异常");
            return null;
        }
    }

    private String getFilePath(){
        String filePath = environment.getProperty("path.export.history");
        String day = DateUtil.format(new Date(), "yyyyMMdd");
        String uuid = UUID.fastUUID().toString();
        return filePath.replace("{day}", day).replace("{uuid}", uuid);
    }

}
